﻿Imports System.Collections.Generic
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Media3D
Imports Cover_Flow_Final.CoverFlow
Imports System.Data.SqlTypes

Public Class CoverFlowControl
    Inherits UserControl

#Region "Fields"
    Public Const HalfRealizedCount As Integer = 7
    Public Const PageSize As Integer = HalfRealizedCount
    Private ReadOnly coverFactory As ICoverFactory
    Private ReadOnly imageList As New Dictionary(Of Integer, ImageInfo)()
    Private ReadOnly coverList As New Dictionary(Of Integer, ICover)()
    Private m_index As Integer
    Private firstRealized As Integer = -1
    Private lastRealized As Integer = -1
#End Region

#Region "Private stuff"

    Private Sub RotateCover(pos As Integer, animate As Boolean)
        If coverList.ContainsKey(pos) Then
            coverList(pos).Animate(m_index, animate)
        End If

    End Sub

    Private Sub UpdateIndex(newIndex As Integer)
        If m_index <> newIndex Then
            Dim animate As Boolean = Math.Abs(newIndex - m_index) < PageSize
            UpdateRange(newIndex)
            Dim oldIndex As Integer = m_index
            m_index = newIndex
            If m_index > oldIndex Then
                If oldIndex < firstRealized Then
                    oldIndex = firstRealized
                End If
                For i As Integer = oldIndex To m_index
                    RotateCover(i, animate)
                Next
            Else
                If oldIndex > lastRealized Then
                    oldIndex = lastRealized
                End If
                For i As Integer = oldIndex To m_index Step -1
                    RotateCover(i, animate)
                Next
            End If
            camera.Position = New Point3D(Cover.CoverStep * m_index, camera.Position.Y, camera.Position.Z)
        End If
    End Sub
    Private Sub viewPort_MouseDown(sender As Object, e As MouseButtonEventArgs)
        Dim rayMeshResult = DirectCast(VisualTreeHelper.HitTest(viewPort, e.GetPosition(viewPort)), RayMeshGeometry3DHitTestResult)
        If rayMeshResult IsNot Nothing Then
            For Each i As Integer In coverList.Keys
                If Not coverList.ContainsKey(i) Then
                    Continue For
                End If
                If coverList(i).Matches(rayMeshResult.MeshHit) Then
                    UpdateIndex(i)
                    Exit For
                End If
            Next
        End If
    End Sub

    Private Sub RemoveCover(pos As Integer)
        If coverList.ContainsKey(pos) Then
            coverList(pos).Destroy()
            coverList.Remove(pos)
        End If

    End Sub
    Private Sub UpdateRange(newIndex As Integer)
        Dim newFirstRealized As Integer = Math.Max(newIndex - HalfRealizedCount, 0)
        Dim newLastRealized As Integer = Math.Min(newIndex + HalfRealizedCount, imageList.Count - 1)
        If lastRealized < newFirstRealized OrElse firstRealized > newLastRealized Then
            visualModel.Children.Clear()
            coverList.Clear()
        ElseIf firstRealized < newFirstRealized Then
            For i As Integer = firstRealized To newFirstRealized - 1
                RemoveCover(i)
            Next
        ElseIf newLastRealized < lastRealized Then
            For i As Integer = lastRealized To newLastRealized + 1 Step -1
                RemoveCover(i)
            Next
        End If
        For i As Integer = newFirstRealized To newLastRealized
            If Not coverList.ContainsKey(i) Then
                Dim cover As ICover = coverFactory.NewCover(imageList(i).Host, imageList(i).Path, i, newIndex)
                coverList.Add(i, cover)
            End If
        Next
        firstRealized = newFirstRealized
        lastRealized = newLastRealized
    End Sub

    Protected ReadOnly Property FirstRealizedIndex() As Integer
        Get
            Return firstRealized
        End Get
    End Property
    Protected ReadOnly Property LastRealizedIndex() As Integer
        Get
            Return lastRealized
        End Get
    End Property
    Private Sub Add(info As ImageInfo)
        imageList.Add(imageList.Count, info)
        UpdateRange(m_index)
    End Sub
#End Region

    Public Sub New()

        InitializeComponent()

        coverFactory = New CoverFactory(visualModel)


    End Sub
    Public WriteOnly Property Cache() As IThumbnailManager
        Set(value As IThumbnailManager)
            Cover.Cache = value
        End Set
    End Property
    Public Sub GoToNext()
        If coverList.Count <> 0 Then
            UpdateIndex(Math.Min(m_index + 1, imageList.Count - 1))
        End If

    End Sub
    Public Sub GoToPrevious()
        If coverList.Count <> 0 Then
            UpdateIndex(Math.Max(m_index - 1, 0))
        End If
    End Sub
    Public Sub GoToNextPage()
        UpdateIndex(Math.Min(m_index + PageSize, imageList.Count - 1))
    End Sub
    Public Sub GoToPreviousPage()
        UpdateIndex(Math.Max(m_index - PageSize, 0))
    End Sub
    Public ReadOnly Property Count() As Integer
        Get
            Return imageList.Count
        End Get
    End Property
    Public Property Index() As Integer
        Get
            Return m_index
        End Get
        Set(value As Integer)
            UpdateIndex(value)
        End Set
    End Property


    Public Sub Add(host As String, imagePath As SqlBinary)
        Add(New ImageInfo(host, imagePath))

    End Sub

#Region "Funciones del Cover"

    Public Sub Recargar()
        imageList.Clear()
        visualModel.Children.Clear()
        coverList.Clear()
    End Sub

    Public Function CoverName(index As Integer) As String
        Return imageList(index).Host
    End Function


#End Region

End Class

